home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-19 / iritsm3s.zip / FREEFORM.C < prev    next >
C/C++ Source or Header  |  1992-01-25  |  44KB  |  1,349 lines

  1. /*****************************************************************************
  2. *   "Irit" - the 3d polygonal solid modeller.                     *
  3. *                                         *
  4. * Written by:  Gershon Elber                Ver 0.2, Mar. 1990   *
  5. ******************************************************************************
  6. *   Module to provide the required interfact for the cagd library for the    *
  7. * free form surfaces and curves.                         *
  8. *****************************************************************************/
  9.  
  10. #include <stdio.h>
  11. #include <math.h>
  12. #include "program.h"
  13. #include "allocate.h"
  14. #include "attribut.h"
  15. #include "objects.h"
  16. #include "primitiv.h"
  17. #include "windows.h"
  18. #include "freeform.h"
  19. #include "graphgen.h"
  20.  
  21. static void ConvertCtlPt(ObjectStruct *PObjPt, CagdCtlPtStruct *CagdPt);
  22. static ObjectStruct *GetControlMesh(ObjectStruct *LstObjList,
  23.                     int UOrder, int VOrder,
  24.                     CagdGeomType GType, char **ErrStr);
  25. static ObjectStruct *GetControlPoly(ObjectStruct *PtObjList, int Order,
  26.                     CagdGeomType GType, char **ErrStr);
  27. static CagdRType *GetKnotVector(ObjectStruct *KntObjList, int Order,
  28.              CagdRType *KnotVector, int *Length, char **ErrStr);
  29. static PolygonStruct *CagdPolys2IritPolys(CagdPolylineStruct *CagdPolys);
  30.  
  31. /*****************************************************************************
  32. *  Conver control point from IRIT to CAGD format.                 *
  33. *****************************************************************************/
  34. static void ConvertCtlPt(ObjectStruct *PObjPt, CagdCtlPtStruct *CagdPt)
  35. {
  36.     int i;
  37.     CagdPointType
  38.     PtType = PObjPt -> U.CtlPt.PtType;
  39.     int PtSize = CAGD_IS_RATIONAL_PT(PtType) + CAGD_NUM_OF_PT_COORD(PtType);
  40.     CagdRType
  41.     *v = PObjPt -> U.CtlPt.Coords;
  42.  
  43.     CagdPt -> PtType = PtType;
  44.  
  45.     if (CAGD_IS_RATIONAL_PT(PtType))
  46.     for (i = 0; i < PtSize; i++) CagdPt -> Coords[i] = *v++;
  47.     else 
  48.     for (i = 1; i <= PtSize; i++) CagdPt -> Coords[i] = *++v;
  49. }
  50.  
  51. /*****************************************************************************
  52. *  Routine to fetch the boolean object DrawCtlPt.                 *
  53. *****************************************************************************/
  54. int GetDrawCtlPt(void)
  55. {
  56.     int DrawCtlPt;
  57.     ObjectStruct *PObj = GetObject("DRAWCTLPT");
  58.  
  59.     if (PObj == NULL || !IS_NUM_OBJ(PObj)) {
  60.     WndwInputWindowPutStr("No numeric object name DRAWCTLPT is defined");
  61.     DrawCtlPt = 0;
  62.     }
  63.     else
  64.     DrawCtlPt = REAL_TO_INT(PObj -> U.R);
  65.  
  66.     return DrawCtlPt;
  67. }
  68.  
  69. /*****************************************************************************
  70. *  Routine to fetch the boolean object DrawCtlPt.                 *
  71. *****************************************************************************/
  72. int GetFourPerFlat(void)
  73. {
  74.     int FourPerFlat;
  75.     ObjectStruct *PObj = GetObject("FLAT4PLY");
  76.  
  77.     if (PObj == NULL || !IS_NUM_OBJ(PObj)) {
  78.     WndwInputWindowPutStr("No numeric object name FLAT4PLY is defined");
  79.     FourPerFlat = 0;
  80.     }
  81.     else
  82.     FourPerFlat = REAL_TO_INT(PObj -> U.R);
  83.  
  84.     return FourPerFlat;
  85. }
  86.  
  87. /*****************************************************************************
  88. * Routine to copy the control mesh lists to the surface control mesh.        *
  89. *   The surface is allocated here as well.                     *
  90. *   Returns the surface if o.k., otherwise NULL.                 *
  91. *****************************************************************************/
  92. static ObjectStruct *GetControlMesh(ObjectStruct *LstObjList,
  93.                     int UOrder, int VOrder,
  94.                     CagdGeomType GType, char **ErrStr)
  95. {
  96.     int i, j, k, PtSize, NumVertices,
  97.     NumVerticesFirst = -1,
  98.         NumLists = 0;
  99.     CagdRType **r;
  100.     RealType *v;
  101.     ObjectStruct *SrfObj, *LstObj, *PtObj;
  102.     CagdPointType
  103.     PtType = CAGD_PT_E3_TYPE;
  104.  
  105.     if (!IS_OLST_OBJ(LstObjList))
  106.     FatalError("SURFACE: Not object list object!");
  107.  
  108.     while ((LstObj = LstObjList -> U.PObjList[NumLists]) != NULL &&
  109.            NumLists < MAX_OBJ_LIST) {
  110.     if (!IS_OLST_OBJ(LstObj)) {
  111.         *ErrStr = "None list object found in list";
  112.         return NULL;
  113.     }
  114.  
  115.         NumVertices = 0;
  116.         while ((PtObj = LstObj -> U.PObjList[NumVertices]) != NULL &&
  117.                NumVertices < MAX_OBJ_LIST) {
  118.         if (!IS_CTLPT_OBJ(PtObj)) {
  119.         *ErrStr = "None point object found in list";
  120.         return NULL;
  121.         }
  122.         if (NumVertices++ == 0 && NumLists == 0)           /* First one. */
  123.         PtType = PtObj -> U.CtlPt.PtType;
  124.             else if (PtType != PtObj -> U.CtlPt.PtType) {
  125.             *ErrStr = "Different point types found in list";
  126.             return NULL;
  127.             }
  128.     }
  129.     if (NumLists++ == 0)
  130.         NumVerticesFirst = NumVertices;
  131.         else
  132.         if (NumVerticesFirst != NumVertices) {
  133.             *ErrStr = "Different size of point lists";
  134.             return NULL;
  135.             }
  136.  
  137.     }
  138.  
  139.     if (NumVertices < 2 || NumLists < 2) {
  140.     *ErrStr = "Less than 2 points in a row/col";
  141.     return NULL;
  142.     }
  143.  
  144.     SrfObj = GenSrfObject("", NULL, NULL);
  145.     switch (GType) {
  146.     case CAGD_SBEZIER_TYPE:
  147.         SrfObj -> U.Srf.Srf = BzrSrfNew(NumVertices, NumLists, PtType);
  148.         break;
  149.     case CAGD_SBSPLINE_TYPE:
  150.         SrfObj -> U.Srf.Srf = BspSrfNew(NumVertices, NumLists,
  151.                         UOrder, VOrder, PtType);
  152.         break;
  153.     }
  154.     SetObjectColor(SrfObj, GlblPrimColor);       /* Set its default color. */
  155.     PtSize = CAGD_IS_RATIONAL_PT(PtType) + CAGD_NUM_OF_PT_COORD(PtType);
  156.  
  157.     for (r = SrfObj -> U.Srf.Srf -> Points, i = 0; i < NumLists; i++) {
  158.     LstObj = LstObjList -> U.PObjList[i];
  159.  
  160.         for (j = 0; j < NumVertices; j++) {
  161.         v = LstObj -> U.PObjList[j] -> U.CtlPt.Coords;
  162.  
  163.         if (CAGD_IS_RATIONAL_PT(PtType))
  164.         for (k = 0; k < PtSize; k++) r[k][i * NumVertices + j] = *v++;
  165.         else
  166.         for (k = 1; k <= PtSize; k++) r[k][i * NumVertices + j] = *++v;
  167.         }
  168.     }
  169.  
  170.     return SrfObj;
  171. }
  172.  
  173. /*****************************************************************************
  174. * Routine to copy the control polygon list to the curve control polygon.     *
  175. *   The curve is allocated here as well.                     *
  176. *   Returns the curve if o.k., otherwise NULL.                     *
  177. *****************************************************************************/
  178. static ObjectStruct *GetControlPoly(ObjectStruct *PtObjList, int Order,
  179.                     CagdGeomType GType, char **ErrStr)
  180. {
  181.     int i, j, PtSize,
  182.         NumVertices = 0;
  183.     CagdRType **r;
  184.     RealType *v;
  185.     ObjectStruct *CrvObj, *PtObj;
  186.     CagdPointType
  187.     PtType = CAGD_PT_E3_TYPE;
  188.  
  189.     *ErrStr = NULL;
  190.  
  191.     if (!IS_OLST_OBJ(PtObjList))
  192.     FatalError("CURVE: Not object list object!");
  193.  
  194.     while ((PtObj = PtObjList -> U.PObjList[NumVertices]) != NULL &&
  195.            NumVertices < MAX_OBJ_LIST) {
  196.     if (!IS_CTLPT_OBJ(PtObj))
  197.     {
  198.         *ErrStr = "None point object found in list";
  199.         return NULL;
  200.     }
  201.  
  202.         if (NumVertices++ == 0)                       /* First one. */
  203.         PtType = PtObj -> U.CtlPt.PtType;
  204.         else if (PtType != PtObj -> U.CtlPt.PtType) {
  205.         *ErrStr = "Different point types found in list";
  206.         return NULL;
  207.     }
  208.     }
  209.  
  210.     if (NumVertices < 2) {
  211.     *ErrStr = "Less than 2 points";
  212.     return NULL;
  213.     }
  214.  
  215.     CrvObj = AllocObject("", CURVE_OBJ, NULL);
  216.     switch (GType) {
  217.     case CAGD_CBEZIER_TYPE:
  218.         CrvObj -> U.Crv.Crv = BzrCrvNew(NumVertices, PtType);
  219.         break;
  220.     case CAGD_CBSPLINE_TYPE:
  221.         CrvObj -> U.Crv.Crv = BspCrvNew(NumVertices, Order, PtType);
  222.         break;
  223.     }
  224.     SetObjectColor(CrvObj, GlblPrimColor);       /* Set its default color. */
  225.     PtSize = CAGD_IS_RATIONAL_PT(PtType) + CAGD_NUM_OF_PT_COORD(PtType);
  226.  
  227.     for (r = CrvObj -> U.Crv.Crv -> Points,i = 0; i < NumVertices; i++) {
  228.     v = PtObjList -> U.PObjList[i] -> U.CtlPt.Coords;
  229.  
  230.     if (CAGD_IS_RATIONAL_PT(PtType))
  231.         for (j = 0; j < PtSize; j++) r[j][i] = *v++;
  232.     else
  233.         for (j = 1; j <= PtSize; j++) r[j][i] = *++v;
  234.     }
  235.  
  236.     return CrvObj;
  237. }
  238.  
  239. /*****************************************************************************
  240. *   Routine to copy the list of knots into the knot vector provided.         *
  241. * Returns KnotVector if o.k., NULL otherwise (sets ErrStr to description).   *
  242. *   If Length == 0 it is figured from the parameters and KnotVector is       *
  243. * allocated here.                                 *
  244. *****************************************************************************/
  245. static CagdRType *GetKnotVector(ObjectStruct *KntObjList, int Order,
  246.             CagdRType *KnotVector, int *Length, char **ErrStr)
  247. {
  248.     int NumKnots = 0,
  249.     NewKnotVector = FALSE;
  250.     ObjectStruct *KntObj;
  251.  
  252.     *ErrStr = NULL;
  253.  
  254.     if (!IS_OLST_OBJ(KntObjList))
  255.     FatalError("KNOT: Not object list object!");
  256.  
  257.     if (*Length == 0) {
  258.     while ((KntObj = KntObjList -> U.PObjList[*Length]) != NULL &&
  259.            *Length < MAX_OBJ_LIST) (*Length)++;
  260.     KnotVector = (CagdRType *) MyMalloc(sizeof(CagdRType) * *Length,
  261.                                  ALLOC_OTHER);
  262.     NewKnotVector = TRUE;
  263.     }
  264.  
  265.     while ((KntObj = KntObjList -> U.PObjList[NumKnots]) != NULL &&
  266.        NumKnots < MAX_OBJ_LIST &&
  267.        NumKnots < *Length) {
  268.     if (!IS_NUM_OBJ(KntObj))
  269.     {
  270.         *ErrStr = "None numeric object found in list";
  271.         return NULL;
  272.     }
  273.  
  274.     KnotVector[NumKnots++] = KntObj->U.R;
  275.     }
  276.  
  277.     if (NumKnots == 1 && KnotVector[0] < KV_MIN_LEGAL) {
  278.     switch ((int) (KnotVector[0] - 0.5)) {
  279.         case KV_UNIFORM_OPEN:
  280.         if (NewKnotVector) {
  281.             MyFree((char *) KnotVector, ALLOC_OTHER);
  282.             KnotVector = BspKnotUniformOpen(*Length - Order, Order,
  283.                                     NULL);
  284.         }
  285.         else
  286.             BspKnotUniformOpen(*Length - Order, Order, KnotVector);
  287.         break;
  288.         case KV_UNIFORM_FLOAT:
  289.         if (NewKnotVector) {
  290.             MyFree((char *) KnotVector, ALLOC_OTHER);
  291.             KnotVector = BspKnotUniformFloat(*Length - Order, Order,
  292.                                     NULL);
  293.         }
  294.         else
  295.             BspKnotUniformFloat(*Length - Order, Order, KnotVector);
  296.         break;
  297.         default:
  298.         *ErrStr = "Invalid knot value";
  299.         fprintf(stderr,"Knot = %10.6lg (%d)",
  300.             KnotVector[0], (int) (KnotVector[0] - 0.5));
  301.         return NULL;
  302.     }
  303.     }
  304.     else if (NumKnots != *Length) {
  305.     *ErrStr = "Wrong knot vector length";
  306.     return NULL;
  307.     }
  308.  
  309.     return KnotVector;
  310. }
  311.  
  312. /*****************************************************************************
  313. *   Routine to create a Bezier surface geometric object defined by a list of *
  314. * lists of vertices.                                 *
  315. *****************************************************************************/
  316. ObjectStruct *GenBezierSurfaceObject(ObjectStruct *LstObjList)
  317. {
  318.     char *ErrStr, Line[LINE_LEN];
  319.     ObjectStruct *SrfObj = GetControlMesh(LstObjList, -1, -1,
  320.                       CAGD_SBEZIER_TYPE, &ErrStr);
  321.  
  322.     if (SrfObj == NULL) {
  323.     sprintf(Line, "SBEZIER: %s, empty object result.\n", ErrStr);
  324.     WndwInputWindowPutStr(Line);
  325.     }
  326.  
  327.     return SrfObj;
  328. }
  329.  
  330. /*****************************************************************************
  331. *   Routine to create a Bezier curve geometric object defined by a list of   *
  332. * vertices.                                     *
  333. *****************************************************************************/
  334. ObjectStruct *GenBezierCurveObject(ObjectStruct *PtObjList)
  335. {
  336.     char *ErrStr, Line[LINE_LEN];
  337.     ObjectStruct *CrvObj = GetControlPoly(PtObjList, -1, CAGD_CBEZIER_TYPE,
  338.                       &ErrStr);
  339.  
  340.     if (CrvObj == NULL) {
  341.     sprintf(Line, "CBEZIER: %s\n, empty object result.", ErrStr);
  342.     WndwInputWindowPutStr(Line);
  343.     }
  344.  
  345.     return CrvObj;
  346. }
  347.  
  348.  
  349. /*****************************************************************************
  350. *   Routine to create a Bspline surface geometric object defined by a list   *
  351. * of vertices.                                     *
  352. *****************************************************************************/
  353. ObjectStruct *GenBsplineSurfaceObject(RealType *RUOrder, RealType *RVOrder,
  354.               ObjectStruct *LstObjList, ObjectStruct *KntObjList)
  355. {
  356.     int Len1, Len2,
  357.     UOrder = REAL_PTR_TO_INT(RUOrder),
  358.     VOrder = REAL_PTR_TO_INT(RVOrder);
  359.     char *ErrStr, Line[LINE_LEN];
  360.     ObjectStruct
  361.     *SrfObj = GetControlMesh(LstObjList, UOrder, VOrder,
  362.                       CAGD_SBSPLINE_TYPE, &ErrStr);
  363.  
  364.     if (SrfObj == NULL) {
  365.     sprintf(Line, "SBSPLINE: %s, empty object result.\n", ErrStr);
  366.     WndwInputWindowPutStr(Line);
  367.     return NULL;
  368.     }
  369.  
  370.     if (KntObjList -> U.PObjList[0] == NULL ||
  371.     KntObjList -> U.PObjList[1] == NULL ||
  372.     KntObjList -> U.PObjList[2] != NULL) {
  373.     WndwInputWindowPutStr("SBSPLINE: Exactly two knot vectors expected");
  374.     MyFree((char *) SrfObj, ALLOC_OBJECT);
  375.     return NULL;
  376.     }
  377.  
  378.     Len1 = SrfObj->U.Srf.Srf->ULength + UOrder;
  379.     Len2 = SrfObj->U.Srf.Srf->VLength + VOrder;
  380.     if (!GetKnotVector(KntObjList -> U.PObjList[0], UOrder,
  381.                SrfObj->U.Srf.Srf->UKnotVector, &Len1, &ErrStr) ||
  382.     !GetKnotVector(KntObjList -> U.PObjList[1], VOrder,
  383.                SrfObj->U.Srf.Srf->VKnotVector, &Len2, &ErrStr)) {
  384.     sprintf(Line, "SBSPLINE: %s, empty object result.\n", ErrStr);
  385.     WndwInputWindowPutStr(Line);
  386.     MyFree((char *) SrfObj, ALLOC_OBJECT);
  387.     return NULL;
  388.     }
  389.  
  390.     return SrfObj;
  391.  
  392. }
  393.  
  394. /*****************************************************************************
  395. *   Routine to create a Bspline curve geometric object defined by a list of  *
  396. * vertices.                                     *
  397. *****************************************************************************/
  398. ObjectStruct *GenBsplineCurveObject(RealType *ROrder, ObjectStruct *PtObjList,
  399.                               ObjectStruct *KntObjList)
  400. {
  401.     int Len,
  402.     Order = REAL_PTR_TO_INT(ROrder);
  403.     char *ErrStr, Line[LINE_LEN];
  404.     ObjectStruct
  405.     *CrvObj = GetControlPoly(PtObjList, Order, CAGD_CBSPLINE_TYPE, &ErrStr);
  406.  
  407.     if (CrvObj == NULL) {
  408.     sprintf(Line, "CBSPLINE: %s, empty object result.\n", ErrStr);
  409.     WndwInputWindowPutStr(Line);
  410.     return NULL;
  411.     }
  412.  
  413.     if (!IS_OLST_OBJ(KntObjList))
  414.     FatalError("CBSPLINE: Knots is not object list object!");
  415.  
  416.     Len = CrvObj->U.Crv.Crv->Length + Order;
  417.     if (!GetKnotVector(KntObjList, Order, CrvObj->U.Crv.Crv->KnotVector,
  418.                &Len, &ErrStr)) {
  419.     sprintf(Line, "CBSPLINE: %s, empty object result.\n", ErrStr);
  420.     WndwInputWindowPutStr(Line);
  421.     MyFree((char *) CrvObj, ALLOC_OBJECT);
  422.     return NULL;
  423.     }
  424.  
  425.     return CrvObj;
  426. }
  427.  
  428. /*****************************************************************************
  429. * Routine to subdivide a surface into two in specified direction (1 or 2)    *
  430. * and specified parameter value.                         *
  431. *****************************************************************************/
  432. ObjectStruct *DivideSurfaceObject(ObjectStruct *SrfObj, RealType *RDir,
  433.                             RealType *ParamVal)
  434. {
  435.     int Dir = REAL_PTR_TO_INT(RDir);
  436.     CagdSrfStruct
  437.     *Srf = CagdSrfSubdivAtParam(SrfObj -> U.Srf.Srf, *ParamVal, Dir);
  438.     ObjectStruct *Srf1, *Srf2, *SrfList;
  439.  
  440.     if (Srf == NULL) return NULL;
  441.  
  442.     Srf1 = GenSrfObject("", Srf, NULL),
  443.     SetObjectColor(Srf1, GetObjectColor(SrfObj));
  444.     Srf2 = GenSrfObject("", Srf->Pnext, NULL),
  445.     SetObjectColor(Srf2, GetObjectColor(SrfObj));
  446.     Srf -> Pnext = NULL;
  447.  
  448.     SrfList = AllocObject("", OBJ_LIST_OBJ, NULL);
  449.     SrfList -> U.PObjList[0] = Srf1;
  450.     SrfList -> U.PObjList[1] = Srf2;
  451.     SrfList -> U.PObjList[2] = NULL;
  452.  
  453.     return SrfList;
  454. }
  455.  
  456. /*****************************************************************************
  457. * Routine to extract a surface region in specified direction (1 or 2) and    *
  458. * specified parameter values.                             *
  459. *****************************************************************************/
  460. ObjectStruct *RegionFromSurfaceObject(ObjectStruct *SrfObj, RealType *RDir,
  461.                       RealType *ParamVal1, RealType *ParamVal2)
  462. {
  463.     int Dir = REAL_PTR_TO_INT(RDir);
  464.     CagdSrfStruct
  465.     *Srf = CagdSrfRegionFromSrf(SrfObj -> U.Srf.Srf,
  466.                     *ParamVal1, *ParamVal2, Dir);
  467.  
  468.     if (Srf == NULL) return NULL;
  469.  
  470.     SrfObj = GenSrfObject("", Srf, NULL);
  471.  
  472.     return SrfObj;
  473. }
  474.  
  475. /*****************************************************************************
  476. * Routine to subdivide a curve into two in specified parameter value.         *
  477. *****************************************************************************/
  478. ObjectStruct *DivideCurveObject(ObjectStruct *CrvObj, RealType *ParamVal)
  479. {
  480.     CagdCrvStruct
  481.     *Crv = CagdCrvSubdivAtParam(CrvObj -> U.Crv.Crv, *ParamVal);
  482.     ObjectStruct *Crv1, *Crv2, *CrvList;
  483.  
  484.     if (Crv == NULL) return NULL;
  485.  
  486.     Crv1 = GenCrvObject("", Crv, NULL),
  487.     SetObjectColor(Crv1, GetObjectColor(CrvObj));
  488.     Crv2 = GenCrvObject("", Crv->Pnext, NULL),
  489.     SetObjectColor(Crv2, GetObjectColor(CrvObj));
  490.     Crv -> Pnext = NULL;
  491.  
  492.     CrvList = AllocObject("", OBJ_LIST_OBJ, NULL);
  493.     CrvList -> U.PObjList[0] = Crv1;
  494.     CrvList -> U.PObjList[1] = Crv2;
  495.     CrvList -> U.PObjList[2] = NULL;
  496.  
  497.     return CrvList;
  498. }
  499.  
  500. /*****************************************************************************
  501. * Routine to extract a curve region in specified parameter values.         *
  502. *****************************************************************************/
  503. ObjectStruct *RegionFromCurveObject(ObjectStruct *CrvObj,
  504.                     RealType *ParamVal1, RealType *ParamVal2)
  505. {
  506.     CagdCrvStruct
  507.     *Crv = CagdCrvRegionFromCrv(CrvObj -> U.Crv.Crv, *ParamVal1, *ParamVal2);
  508.  
  509.     if (Crv == NULL) return NULL;
  510.  
  511.     CrvObj = GenCrvObject("", Crv, NULL);
  512.  
  513.     return CrvObj;
  514. }
  515.  
  516. /*****************************************************************************
  517. * Routine to refine surface in specified direction (1 or 2) and knot vector. *
  518. * If, however, Replace is non zero, KnotsObj REPLACES current vector.        *
  519. *****************************************************************************/
  520. ObjectStruct *RefineSurfaceObject(ObjectStruct *SrfObj, RealType *RDir,
  521.                   RealType *RReplace, ObjectStruct *KnotsObj)
  522. {
  523.     int n = 0,
  524.     Replace = REAL_PTR_TO_INT(RReplace),
  525.     Dir = REAL_PTR_TO_INT(RDir);
  526.     char *ErrStr, Line[LINE_LEN];
  527.     CagdRType
  528.     *t = GetKnotVector(KnotsObj, 0, NULL, &n, &ErrStr);
  529.     CagdSrfStruct *RefSrf;
  530.     ObjectStruct *RefSrfObj;
  531.  
  532.     if (t == NULL) {
  533.     sprintf(Line, "REFINE: %s, empty object result.\n", ErrStr);
  534.     WndwInputWindowPutStr(Line);
  535.     MyFree((char *) SrfObj, ALLOC_OBJECT);
  536.     return NULL;
  537.     }
  538.     RefSrf = CagdSrfRefineAtParams(SrfObj -> U.Srf.Srf, Dir, Replace, t, n);
  539.     MyFree((char *) t, ALLOC_OTHER);
  540.     if (RefSrf == NULL) return NULL;
  541.  
  542.     RefSrfObj = GenSrfObject("", RefSrf, NULL),
  543.     SetObjectColor(RefSrfObj, GetObjectColor(SrfObj));
  544.     return RefSrfObj;
  545. }
  546.  
  547. /*****************************************************************************
  548. * Routine to refine curve in specified knot vector.                 *
  549. * If, however, Replace is non zero, knotsObj REPLACES current vector.        *
  550. *****************************************************************************/
  551. ObjectStruct *RefineCurveObject(ObjectStruct *CrvObj, RealType *RReplace,
  552.                             ObjectStruct *KnotsObj)
  553. {
  554.     int n = 0,
  555.     Replace = REAL_PTR_TO_INT(RReplace);
  556.     char *ErrStr, Line[LINE_LEN];
  557.     CagdRType
  558.     *t = GetKnotVector(KnotsObj, 0, NULL, &n, &ErrStr);
  559.     CagdCrvStruct *RefCrv;
  560.     ObjectStruct *RefCrvObj;
  561.  
  562.     if (t == NULL) {
  563.     sprintf(Line, "REFINE: %s, empty object result.\n", ErrStr);
  564.     WndwInputWindowPutStr(Line);
  565.     MyFree((char *) CrvObj, ALLOC_OBJECT);
  566.     return NULL;
  567.     }
  568.     RefCrv = CagdCrvRefineAtParams(CrvObj -> U.Crv.Crv, Replace, t, n);
  569.     MyFree((char *) t, ALLOC_OTHER);
  570.     if (RefCrv == NULL) return NULL;
  571.  
  572.     RefCrvObj = GenCrvObject("", RefCrv, NULL),
  573.     SetObjectColor(RefCrvObj, GetObjectColor(CrvObj));
  574.     return RefCrvObj;
  575. }
  576.  
  577. /*****************************************************************************
  578. * Routine to evaluate surface in specified parameter values.             *
  579. *****************************************************************************/
  580. ObjectStruct *EvalSurfaceObject(ObjectStruct *SrfObj, RealType *u, RealType *v)
  581. {
  582.     CagdRType *Pt = CagdSrfEval(SrfObj -> U.Srf.Srf, *u, *v);
  583.     ObjectStruct *CtlPtObj = GenCtlPtObject("", SrfObj -> U.Srf.Srf -> PType,
  584.                                   Pt, NULL, NULL);
  585.  
  586.     return CtlPtObj;
  587. }
  588.  
  589. /*****************************************************************************
  590. * Routine to evaluate curve in specified parameter value.             *
  591. *****************************************************************************/
  592. ObjectStruct *EvalCurveObject(ObjectStruct *CrvObj, RealType *t)
  593. {
  594.     CagdRType
  595.     *Pt = CagdCrvEval(CrvObj -> U.Crv.Crv, *t);
  596.     ObjectStruct *CtlPtObj = GenCtlPtObject("", CrvObj -> U.Crv.Crv -> PType,
  597.                                   Pt, NULL, NULL);
  598.  
  599.     return CtlPtObj;
  600. }
  601.  
  602. /*****************************************************************************
  603. * Routine to evaluate surface normal in specified parameter values.             *
  604. *****************************************************************************/
  605. ObjectStruct *NormalSurfaceObject(ObjectStruct *SrfObj, RealType *u,
  606.                                   RealType *v)
  607. {
  608.     int i;
  609.     RealType V[3];
  610.     CagdVecStruct
  611.     *Vec = CagdSrfNormal(SrfObj -> U.Srf.Srf, *u, *v);
  612.     ObjectStruct *NormalObj;
  613.  
  614.     for (i = 0; i < 3; i++) V[i] = Vec -> Vec[i];
  615.  
  616.     NormalObj = GenVecObject("", &V[0], &V[1], &V[2], NULL);
  617.  
  618.     return NormalObj;
  619. }
  620.  
  621. /*****************************************************************************
  622. * Routine to evaluate surface tangent in specified parameter value and dir.. *
  623. *****************************************************************************/
  624. ObjectStruct *TangentSurfaceObject(ObjectStruct *SrfObj, RealType *RDir,
  625.                              RealType *u, RealType *v)
  626. {
  627.     int i,
  628.     Dir = REAL_PTR_TO_INT(RDir);
  629.     RealType V[3];
  630.     CagdVecStruct
  631.     *Vec = CagdSrfTangent(SrfObj -> U.Srf.Srf, *u, *v, Dir);
  632.     ObjectStruct *TangentObj;
  633.  
  634.     for (i = 0; i < 3; i++) V[i] = Vec -> Vec[i];
  635.  
  636.     TangentObj = GenVecObject("", &V[0], &V[1], &V[2], NULL);
  637.  
  638.     return TangentObj;
  639. }
  640.  
  641. /*****************************************************************************
  642. * Routine to evaluate curve in specified parameter value.             *
  643. *****************************************************************************/
  644. ObjectStruct *TangentCurveObject(ObjectStruct *CrvObj, RealType *t)
  645. {
  646.     int i;
  647.     RealType V[3];
  648.     CagdVecStruct
  649.     *Vec = CagdCrvTangent(CrvObj -> U.Crv.Crv, *t);
  650.     ObjectStruct *TangentObj;
  651.  
  652.     for (i = 0; i < 3; i++) V[i] = Vec -> Vec[i];
  653.  
  654.     TangentObj = GenVecObject("", &V[0], &V[1], &V[2], NULL);
  655.  
  656.     return TangentObj;
  657. }
  658.  
  659. /*****************************************************************************
  660. * Routine to extract an isoparametric curve out of a surface.             *
  661. *****************************************************************************/
  662. ObjectStruct *CurveFromSurface(ObjectStruct *SrfObj, RealType *RDir,
  663.                                 RealType *ParamVal)
  664. {
  665.     int Dir = REAL_PTR_TO_INT(RDir);
  666.     CagdCrvStruct
  667.     *Crv = CagdCrvFromSrf(SrfObj -> U.Srf.Srf, *ParamVal, Dir);
  668.     ObjectStruct *CrvObj;
  669.  
  670.     if (Crv == NULL) return NULL;
  671.  
  672.     CrvObj = GenCrvObject("", Crv, NULL);
  673.  
  674.     return CrvObj;
  675. }
  676.  
  677. /*****************************************************************************
  678. * Routine to extract an isoparametric curve out of a surface mesh.         *
  679. *****************************************************************************/
  680. ObjectStruct *CurveFromSrfMesh(ObjectStruct *SrfObj, RealType *RDir,
  681.                             RealType *RIndex)
  682. {
  683.     int Dir = REAL_PTR_TO_INT(RDir),
  684.     Index = REAL_PTR_TO_INT(RIndex);
  685.     CagdCrvStruct
  686.     *Crv = CagdCrvFromMesh(SrfObj -> U.Srf.Srf, Index, Dir);
  687.     ObjectStruct *CrvObj;
  688.  
  689.     if (Crv == NULL) return NULL;
  690.  
  691.     CrvObj = GenCrvObject("", Crv, NULL);
  692.  
  693.     return CrvObj;
  694. }
  695.  
  696. /*****************************************************************************
  697. * Routine to reverse a curve.                             *
  698. *****************************************************************************/
  699. ObjectStruct *CurveReverse(ObjectStruct *CrvObj)
  700. {
  701.      CagdCrvStruct
  702.     *RevCrv = CagdCrvReverse(CrvObj -> U.Crv.Crv);
  703.  
  704.     if (RevCrv == NULL) return NULL;
  705.  
  706.     CrvObj = GenCrvObject("", RevCrv, NULL);
  707.  
  708.     return CrvObj;
  709. }
  710.  
  711. /*****************************************************************************
  712. * Routine to reverse a surface.                             *
  713. *****************************************************************************/
  714. ObjectStruct *SurfaceReverse(ObjectStruct *SrfObj)
  715. {
  716.     CagdSrfStruct
  717.     *RevSrf = CagdSrfReverse(SrfObj -> U.Srf.Srf);
  718.  
  719.     if (RevSrf == NULL) return NULL;
  720.  
  721.     SrfObj = GenSrfObject("", RevSrf, NULL);
  722.  
  723.     return SrfObj;
  724. }
  725.  
  726. /*****************************************************************************
  727. * Routine to convert a curve to a piecewise linear polyline approximation    *
  728. * and convert its control polygon into polyline as well.             *
  729. * Result is saved in the PLPolys/CtlPoly curve slots.                 *
  730. * If however approximation alread exists, no computation is performed.       *
  731. *****************************************************************************/
  732. void ComputeCurveIsoLines(ObjectStruct *PObj)
  733. {
  734.     int i, j,
  735.     DrawCtlPtColor = GetDrawCtlPt(),
  736.     Resolution = GetResolution(TRUE),
  737.     RealResolution = GetResolution(FALSE);
  738.  
  739.     if (!IS_CRV_OBJ(PObj))
  740.     FatalError("Curve was expected.");
  741.  
  742.     if (RealResolution > 0 && PObj -> U.Crv.PLPolys == NULL) {
  743.         for (i = 1, j = Resolution; j > 0 && i < 10; i++, j >>= 1);
  744.         BzrCrvSetCache(i, TRUE);
  745.     PObj -> U.Crv.PLPolys = CagdCrv2Polyline(PObj -> U.Crv.Crv, i);
  746.     }
  747.     if (DrawCtlPtColor && PObj -> U.Crv.CtlPoly == NULL) {
  748.     PObj -> U.Crv.CtlPoly = CagdCrv2CtrlPoly(PObj -> U.Crv.Crv);
  749.     }
  750. }
  751.  
  752. /*****************************************************************************
  753. * Routine to convert a surface to a set of piecewise linear polylines         *
  754. * approximation and convert its control mesh into set of polyline as well.   *
  755. *  Result is saved in the PLPolys/CtlMsh surface slots.                 *
  756. * If however approximation alread exists, no computation is performed.       *
  757. *****************************************************************************/
  758. void ComputeSurfaceIsoLines(ObjectStruct *PObj)
  759. {
  760.     int i, j,
  761.     DrawCtlPtColor = GetDrawCtlPt(),
  762.     Resolution = GetResolution(TRUE),
  763.     RealResolution = GetResolution(FALSE);
  764.  
  765.     if (!IS_SRF_OBJ(PObj))
  766.     FatalError("Surface was expected.");
  767.  
  768.     if (RealResolution > 0 && PObj -> U.Srf.PLPolys == NULL) {
  769.         for (i = 1, j = Resolution; j > 0 && i < 10; i++, j >>= 1);
  770.         BzrCrvSetCache(i, TRUE);
  771.         PObj -> U.Srf.PLPolys = CagdSrf2Polylines(PObj -> U.Srf.Srf,
  772.                               Resolution, i);
  773.     }
  774.     if (DrawCtlPtColor && PObj -> U.Srf.CtlMesh == NULL) {
  775.         PObj -> U.Srf.CtlMesh = CagdSrf2CtrlMesh(PObj -> U.Srf.Srf);
  776.     }
  777. }
  778.  
  779. /*****************************************************************************
  780. * Routine to convert a surface to a set of polygons approximating it.         *
  781. * Result is saved in the Polygons surface slot.                     *
  782. * If however approximation alread exists, no computation is performed.       *
  783. *****************************************************************************/
  784. void ComputeSurfacePolygons(ObjectStruct *PObj)
  785. {
  786.     int    i, j,
  787.     Resolution = GetResolution(TRUE),
  788.     FourPerFlat = GetFourPerFlat();
  789.     char
  790.     *SrfStrResolution = GetObjectStrAttrib(PObj, "resolution");
  791.     VectorType Vin;
  792.     VertexStruct *V;
  793.     PolygonStruct *P,
  794.     *PHead = NULL;
  795.     CagdPolygonStruct *CagdPoly, *CagdPolys;
  796.  
  797.     if (PObj -> U.Srf.Polygons != NULL) return;
  798.  
  799.     if (SrfStrResolution) {
  800.     float SrfRelResolution;
  801.  
  802.     if (sscanf(SrfStrResolution, "%f", &SrfRelResolution) == 1) {
  803.         Resolution = REAL_TO_INT(Resolution * SrfRelResolution);
  804.     }
  805.     }
  806.  
  807. #ifndef __MSDOS__
  808.     /* Make the resolution more reasonable (very slow on MSDOS). */
  809.     Resolution *= 2;
  810. #endif /* __MSDOS__ */
  811.  
  812.     if (GetObjectStrAttrib(PObj, "twoperflat") != NULL)
  813.     FourPerFlat = FALSE;
  814.     if (GetObjectStrAttrib(PObj, "fourperflat") != NULL)
  815.     FourPerFlat = TRUE;
  816.  
  817.     CagdPolys = CagdSrf2Polygons(PObj -> U.Srf.Srf, Resolution, TRUE,
  818.                                 FourPerFlat);
  819.  
  820.     for (CagdPoly = CagdPolys;
  821.      CagdPoly != NULL;
  822.      CagdPoly = CagdPoly -> Pnext) {
  823.     /* All polygons are triangles! */
  824.     P = AllocPolygon(0, 0, V = AllocVertex(0, 0, NULL, NULL), NULL);
  825.     V -> Pnext = AllocVertex(0, 0, NULL, NULL); V = V -> Pnext;
  826.     V -> Pnext = AllocVertex(0, 0, NULL, NULL); V = V -> Pnext;
  827.     V -> Pnext = P -> V;           /* Make the Vertex list circular. */
  828.  
  829.     SET_CONVEX_POLY(P);               /* Mark it as convex polygon. */
  830.  
  831.     for (i = 0; i < 3; i++) {             /* Convert to vertices. */
  832.         V = V -> Pnext;
  833.  
  834.         for (j = 0; j < 3; j++)                /* Convert to our format. */
  835.         V -> Pt[j] = CagdPoly -> Polygon[i].Pt[j];
  836.         for (j = 0; j < 3; j++)
  837.         V -> Normal[j] = CagdPoly -> Normal[i].Vec[j];
  838.     }
  839.  
  840.     PT_ADD(Vin, CagdPoly -> Polygon[0].Pt, CagdPoly -> Normal[0].Vec);
  841.     UpdatePolyPlane(P, Vin);           /* Update plane equation. */
  842.  
  843.     P -> Pnext = PHead;
  844.     PHead = P;
  845.     }
  846.  
  847.     CagdPolygonFreeList(CagdPolys);
  848.  
  849.     PObj -> U.Srf.Polygons = GenPolyObject("", PHead, NULL);
  850.     SetObjectColor(PObj -> U.Srf.Polygons, GlblPrimColor);
  851. }
  852.  
  853. /*****************************************************************************
  854. * Routine to convert a surface/list of surfaces into set of polygons.         *
  855. *****************************************************************************/
  856. ObjectStruct *Geometry2Polygons(ObjectStruct *Obj)
  857. {
  858.     ObjectStruct *PObj;
  859.  
  860.     if (IS_SRF_OBJ(Obj)) {
  861.     ComputeSurfacePolygons(Obj);
  862.     PObj = CopyObject(NULL, Obj -> U.Srf.Polygons, FALSE);
  863.     SetObjectColor(PObj, GlblPrimColor);       /* Set its default color. */
  864.     return PObj;
  865.     }
  866.     else if (IS_OLST_OBJ(Obj))
  867.     {
  868.     int i = 0;
  869.     PolygonStruct *P;
  870.     ObjectStruct
  871.         *PObjAll = NULL;
  872.  
  873.         while ((PObj = Obj -> U.PObjList[i++]) != NULL && i < MAX_OBJ_LIST) {
  874.         PObj = Geometry2Polygons(PObj);
  875.  
  876.         if (PObjAll) {
  877.         if (PObj -> U.Pl.P) {
  878.             for (P = PObj -> U.Pl.P;
  879.              P -> Pnext != NULL;
  880.              P = P -> Pnext);
  881.             P -> Pnext = PObjAll -> U.Pl.P;
  882.             PObjAll -> U.Pl.P = PObj -> U.Pl.P;
  883.             PObj -> U.Pl.P = NULL;
  884.         }
  885.         MyFree((char *) PObj, ALLOC_OBJECT);
  886.         }
  887.         else {
  888.         PObjAll = PObj;
  889.         }
  890.     }
  891.  
  892.     return PObjAll;
  893.     }
  894.     else {
  895.     WndwInputWindowPutStr("Unconvertable to polygons object ignored");
  896.     return NULL;
  897.     }
  898. }
  899.  
  900. /*****************************************************************************
  901. * Routine to convert Cagd lib polylines to Irit polylines.             *
  902. *****************************************************************************/
  903. static PolygonStruct *CagdPolys2IritPolys(CagdPolylineStruct *CagdPolys)
  904. {
  905.     CagdPolylineStruct *CagdPoly;
  906.     PolygonStruct
  907.     *PHead = NULL;
  908.  
  909.     for (CagdPoly = CagdPolys;
  910.      CagdPoly != NULL;
  911.      CagdPoly = CagdPoly -> Pnext) {
  912.     int i, j;
  913.     VertexStruct *V;
  914.     PolygonStruct *P;
  915.  
  916.     P = AllocPolygon(0, 0, V = AllocVertex(0, 0, NULL, NULL), NULL);
  917.  
  918.     for (i = 0; i < CagdPoly -> Length; i++) {   /* Convert to vertices. */
  919.         for (j = 0; j < 3; j++)                /* Convert to our format. */
  920.         V -> Pt[j] = CagdPoly -> Polyline[i].Pt[j];
  921.  
  922.         if (i < CagdPoly -> Length - 1) {
  923.         V -> Pnext = AllocVertex(0, 0, NULL, NULL);
  924.         V = V -> Pnext;
  925.         }
  926.     }
  927.  
  928.     P -> Pnext = PHead;
  929.     PHead = P;
  930.     }
  931.  
  932.     return PHead;
  933. }
  934.  
  935. /*****************************************************************************
  936. * Routine to convert a surface/curve/list of them into set of polylines.     *
  937. *****************************************************************************/
  938. ObjectStruct *Geometry2Polylines(ObjectStruct *Obj)
  939. {
  940.     ObjectStruct *PObj;
  941.     PolygonStruct *P, *PTail, *PHead;
  942.     int DoMeshes = GetDrawCtlPt();
  943.  
  944.     if (IS_SRF_OBJ(Obj)) {
  945.     ComputeSurfaceIsoLines(Obj);
  946.     if (Obj -> U.Srf.PLPolys != NULL)
  947.             PHead = CagdPolys2IritPolys(Obj -> U.Srf.PLPolys);
  948.     else
  949.         PHead = NULL;
  950.  
  951.     if (DoMeshes && Obj -> U.Srf.CtlMesh != NULL) {
  952.         P = CagdPolys2IritPolys(Obj -> U.Srf.CtlMesh);
  953.  
  954.         for (PTail = P; PTail -> Pnext != NULL; PTail = PTail -> Pnext);
  955.         PTail -> Pnext = PHead;
  956.         PHead = P;
  957.     }
  958.  
  959.     PObj = GenPolyObject("", PHead, NULL);
  960.     SetObjectColor(PObj, GlblPrimColor);       /* Set its default color. */
  961.     SET_POLYLINE_OBJ(PObj);
  962.     return PObj;
  963.     }
  964.     if (IS_CRV_OBJ(Obj)) {
  965.     ComputeCurveIsoLines(Obj);
  966.     if (Obj -> U.Crv.PLPolys != NULL)
  967.             PHead = CagdPolys2IritPolys(Obj -> U.Srf.PLPolys);
  968.     else
  969.         PHead = NULL;
  970.  
  971.     if (DoMeshes && Obj -> U.Crv.CtlPoly != NULL) {
  972.         P = CagdPolys2IritPolys(Obj -> U.Crv.CtlPoly);
  973.  
  974.         for (PTail = P; PTail -> Pnext != NULL; PTail = PTail -> Pnext);
  975.         PTail -> Pnext = PHead;
  976.         PHead = P;
  977.     }
  978.  
  979.     PObj = GenPolyObject("", PHead, NULL);
  980.     SetObjectColor(PObj, GlblPrimColor);           /* Set its default color. */
  981.     SET_POLYLINE_OBJ(PObj);
  982.     return PObj;
  983.     }
  984.     else if (IS_OLST_OBJ(Obj))
  985.     {
  986.     int i = 0;
  987.     ObjectStruct
  988.         *PObjAll = NULL;
  989.  
  990.         while ((PObj = Obj -> U.PObjList[i++]) != NULL && i < MAX_OBJ_LIST) {
  991.         PObj = Geometry2Polylines(PObj);
  992.  
  993.         if (PObjAll) {
  994.         if (PObj -> U.Pl.P) {
  995.             for (P = PObj -> U.Pl.P;
  996.              P -> Pnext != NULL;
  997.              P = P -> Pnext);
  998.             P -> Pnext = PObjAll -> U.Pl.P;
  999.             PObjAll -> U.Pl.P = PObj -> U.Pl.P;
  1000.             PObj -> U.Pl.P = NULL;
  1001.         }
  1002.         MyFree((char *) PObj, ALLOC_OBJECT);
  1003.         }
  1004.         else {
  1005.         PObjAll = PObj;
  1006.         }
  1007.     }
  1008.  
  1009.     return PObjAll;
  1010.     }
  1011.     else {
  1012.     WndwInputWindowPutStr("Unconvertable to polylines object ignored");
  1013.     return NULL;
  1014.     }
  1015. }
  1016.  
  1017. /*****************************************************************************
  1018. * Creates a circle on the XY plane.                         *
  1019. *****************************************************************************/
  1020. ObjectStruct *GenCircleCurveObject(VectorType Position, RealType *Radius)
  1021. {
  1022.     int i;
  1023.     CagdPtStruct Pos;
  1024.     CagdCrvStruct *CircCrv;
  1025.     ObjectStruct *CrvObj;
  1026.  
  1027.     for (i = 0; i < 3; i++) Pos.Pt[i] = Position[i];
  1028.     CircCrv = BspCrvCreateCircle(&Pos, *Radius);
  1029.  
  1030.     if (CircCrv == NULL) return NULL;
  1031.  
  1032.     CrvObj = GenCrvObject("", CircCrv, NULL);
  1033.  
  1034.     return CrvObj;
  1035. }
  1036.  
  1037. /*****************************************************************************
  1038. * Creates an arbitrary arc specified by Two end points and Center. Arc must  *
  1039. * be less than 180 degree.                             *
  1040. *****************************************************************************/
  1041. ObjectStruct *GenArcCurveObject(VectorType Start, VectorType Center,
  1042.                             VectorType End)
  1043. {
  1044.     int i;
  1045.     CagdPtStruct StartPt, CenterPt, EndPt;
  1046.     CagdCrvStruct *ArcCrv;
  1047.     ObjectStruct *CrvObj;
  1048.  
  1049.     for (i = 0; i < 3; i++) {
  1050.     StartPt.Pt[i] = Start[i];
  1051.     CenterPt.Pt[i] = Center[i];
  1052.     EndPt.Pt[i] = End[i];
  1053.     }
  1054.     ArcCrv = BzrCrvCreateArc(&StartPt, &CenterPt, &EndPt);
  1055.  
  1056.     if (ArcCrv == NULL) return NULL;
  1057.  
  1058.     CrvObj = GenCrvObject("", ArcCrv, NULL);
  1059.  
  1060.     return CrvObj;
  1061. }
  1062.  
  1063. /*****************************************************************************
  1064. * Construct a ruled surface out of the two provided curves. The two curves   *
  1065. * must have same point type/curve type/order (and knot vector if Bspline).   *
  1066. *****************************************************************************/
  1067. ObjectStruct *GenRuledSrfObject(ObjectStruct *Crv1, ObjectStruct *Crv2)
  1068. {
  1069.     ObjectStruct *SrfObj;
  1070.     CagdSrfStruct
  1071.     *RuledSrf = CagdRuledSrf(Crv1 -> U.Crv.Crv, Crv2 -> U.Crv.Crv, 2, 2);
  1072.  
  1073.     if (RuledSrf == NULL) return NULL;
  1074.  
  1075.     SrfObj = GenSrfObject("", RuledSrf, NULL);
  1076.  
  1077.     return SrfObj;
  1078. }
  1079.  
  1080. /*****************************************************************************
  1081. * Construct a boolean sum surface out of the four provided curves.         *
  1082. *****************************************************************************/
  1083. ObjectStruct *GenBoolSumSrfObject(ObjectStruct *Crv1, ObjectStruct *Crv2,
  1084.                   ObjectStruct *Crv3, ObjectStruct *Crv4)
  1085. {
  1086.     ObjectStruct *SrfObj;
  1087.     CagdSrfStruct
  1088.     *BoolSumSrf = CagdBoolSumSrf(Crv1 -> U.Crv.Crv,
  1089.                      Crv2 -> U.Crv.Crv,
  1090.                      Crv3 -> U.Crv.Crv,
  1091.                      Crv4 -> U.Crv.Crv);
  1092.  
  1093.     if (BoolSumSrf == NULL) return NULL;
  1094.  
  1095.     SrfObj = GenSrfObject("", BoolSumSrf, NULL);
  1096.  
  1097.     return SrfObj;
  1098. }
  1099.  
  1100. /*****************************************************************************
  1101. * Construct a surface out of the provided curve list.                 *
  1102. *****************************************************************************/
  1103. ObjectStruct *GenSrfFromCrvsObject(ObjectStruct *CrvList)
  1104. {
  1105.     int i,
  1106.     NumCrvs = 0;
  1107.     ObjectStruct *SrfObj, *CrvObj;
  1108.     CagdSrfStruct *Srf;
  1109.  
  1110.  
  1111.     if (!IS_OLST_OBJ(CrvList))
  1112.     FatalError("SURFACE: Not object list object!");
  1113.  
  1114.     while ((CrvObj = CrvList -> U.PObjList[NumCrvs]) != NULL &&
  1115.        NumCrvs < MAX_OBJ_LIST) {
  1116.     if (!IS_CRV_OBJ(CrvObj)) {
  1117.         WndwInputWindowPutStr("SURFACE: List contains non curve object(s).");
  1118.         return NULL;
  1119.     }
  1120.     if (CrvObj -> U.Crv.Crv -> Pnext != NULL) {
  1121.         WndwInputWindowPutStr("SURFACE: nested curve lists are disallowed.");
  1122.         return NULL;
  1123.     }
  1124.     NumCrvs++;
  1125.     }
  1126.  
  1127.     /* Chain all curves into a single list and invoke the srf constructor: */
  1128.     for (i = 0; i < NumCrvs; i++)
  1129.     CrvList -> U.PObjList[i] -> U.Crv.Crv -> Pnext =
  1130.         i < NumCrvs - 1 ? CrvList -> U.PObjList[i + 1] -> U.Crv.Crv : NULL;
  1131.  
  1132.     Srf = CagdSrfFromCrvs(CrvList -> U.PObjList[0] -> U.Crv.Crv);
  1133.  
  1134.     for (i = 0; i < NumCrvs; i++)
  1135.     CrvList -> U.PObjList[i] -> U.Crv.Crv -> Pnext = NULL;
  1136.  
  1137.     if (Srf == NULL) return NULL;
  1138.  
  1139.     SrfObj = GenSrfObject("", Srf, NULL);
  1140.  
  1141.     return SrfObj;
  1142. }
  1143.  
  1144. /*****************************************************************************
  1145. * Construct a Sweep surface out of the CrossSection curve, Axis curve and    *
  1146. * optional Scaling curve and Scaler which scales the CrossSection.         *
  1147. *****************************************************************************/
  1148. ObjectStruct *GenSweepSrfObject(ObjectStruct *CrossSection, ObjectStruct *Axis,
  1149.                      ObjectStruct *ScalingCrv, RealType *Scale)
  1150. {
  1151.     ObjectStruct *SrfObj;
  1152.     CagdSrfStruct
  1153.     *SweepSrf = CagdSweepSrf(CrossSection -> U.Crv.Crv, Axis -> U.Crv.Crv,
  1154.                ScalingCrv ? ScalingCrv -> U.Crv.Crv : NULL, *Scale);
  1155.  
  1156.     if (SweepSrf == NULL) return NULL;
  1157.  
  1158.     SrfObj = GenSrfObject("", SweepSrf, NULL);
  1159.  
  1160.     return SrfObj;
  1161. }
  1162.  
  1163. /*****************************************************************************
  1164. * Computes an approximation to the offset of a (planar) curve or a surface.  *
  1165. *****************************************************************************/
  1166. ObjectStruct *GenOffsetObject(ObjectStruct *Obj, RealType *Offset)
  1167. {
  1168.     if (IS_SRF_OBJ(Obj)) {
  1169.         ObjectStruct *SrfObj;
  1170.         CagdSrfStruct
  1171.         *OffsetSrf = CagdSrfOffset(Obj -> U.Srf.Srf, *Offset);
  1172.  
  1173.         if (OffsetSrf == NULL) return NULL;
  1174.  
  1175.         SrfObj = GenSrfObject("", OffsetSrf, NULL);
  1176.  
  1177.         return SrfObj;
  1178.     }
  1179.     else if (IS_CRV_OBJ(Obj)) {
  1180.         ObjectStruct *CrvObj;
  1181.         CagdCrvStruct
  1182.         *OffsetCrv = CagdCrvOffset(Obj -> U.Crv.Crv, *Offset);
  1183.  
  1184.         if (OffsetCrv == NULL) return NULL;
  1185.  
  1186.         CrvObj = GenCrvObject("", OffsetCrv, NULL);
  1187.  
  1188.         return CrvObj;
  1189.     }
  1190.     else {
  1191.     WndwInputWindowPutStr("Offset allowed on curves/surfaces only");
  1192.     return NULL;
  1193.     }
  1194. }
  1195.  
  1196. /*****************************************************************************
  1197. * Merge two curves/ctl points into one curve by adding a linear segment      *
  1198. * between the first end point to second start point.                 *
  1199. *****************************************************************************/
  1200. ObjectStruct *MergeCurvesAndCtlPoints(ObjectStruct *PObj1, ObjectStruct *PObj2)
  1201. {
  1202.     ObjectStruct *CrvObj;
  1203.     CagdCrvStruct
  1204.     *Crv = NULL;
  1205.     CagdPtStruct Pt1, Pt2;
  1206.  
  1207.     if (IS_CRV_OBJ(PObj1)) {
  1208.     if (IS_CRV_OBJ(PObj2)) {
  1209.         Crv = CagdMergeCrvCrv(PObj1 -> U.Crv.Crv, PObj2 -> U.Crv.Crv);
  1210.     }
  1211.     else if (IS_CTLPT_OBJ(PObj2)) {
  1212.         CagdRType
  1213.         *Coords2 = PObj2 -> U.CtlPt.Coords;
  1214.  
  1215.         CagdCoerceToE3(Pt2.Pt, &Coords2, -1, PObj2 -> U.CtlPt.PtType);
  1216.         Crv = CagdMergeCrvPt(PObj1 -> U.Crv.Crv, &Pt2);
  1217.     }
  1218.     else
  1219.         FatalError("Curve/CtlPt was expected.");
  1220.     }
  1221.     else if (IS_CTLPT_OBJ(PObj1)) {
  1222.     CagdRType
  1223.         *Coords1 = PObj1 -> U.CtlPt.Coords;
  1224.  
  1225.     CagdCoerceToE3(Pt1.Pt, &Coords1, -1, PObj1 -> U.CtlPt.PtType);
  1226.  
  1227.     if (IS_CRV_OBJ(PObj2)) {
  1228.         Crv = CagdMergePtCrv(&Pt1, PObj2 -> U.Crv.Crv);
  1229.     }
  1230.     else if (IS_CTLPT_OBJ(PObj2)) {
  1231.         CagdRType
  1232.         *Coords2 = PObj2 -> U.CtlPt.Coords;
  1233.  
  1234.         CagdCoerceToE3(Pt2.Pt, &Coords2, -1, PObj2 -> U.CtlPt.PtType);
  1235.         Crv = CagdMergePtPt(&Pt1, &Pt2);
  1236.     }
  1237.     else
  1238.         FatalError("Curve/CtlPt was expected.");
  1239.     }
  1240.     else
  1241.     FatalError("Curve/CtlPt was expected.");
  1242.  
  1243.     if (Crv == NULL) return NULL;
  1244.  
  1245.     CrvObj = GenCrvObject("", Crv, NULL);
  1246.  
  1247.     return CrvObj;
  1248. }
  1249.  
  1250. /*****************************************************************************
  1251. *  Editing of a single control point of a curve.                 *
  1252. *****************************************************************************/
  1253. ObjectStruct *EditCrvControlPoint(ObjectStruct *PObjCrv, ObjectStruct *PObjPt,
  1254.                                  RealType *Index)
  1255. {
  1256.     ObjectStruct *CrvObj;
  1257.     CagdCtlPtStruct CagdCtlPt;
  1258.     CagdCrvStruct *Crv;
  1259.  
  1260.     ConvertCtlPt(PObjPt, &CagdCtlPt);
  1261.  
  1262.     Crv = CagdEditSingleCrvPt(PObjCrv -> U.Crv.Crv, &CagdCtlPt,
  1263.                   REAL_PTR_TO_INT(Index));
  1264.  
  1265.     CrvObj = GenCrvObject("", Crv, NULL);
  1266.  
  1267.     return CrvObj;
  1268. }
  1269.  
  1270. /*****************************************************************************
  1271. *  Editing of a single control point of a surface.                 *
  1272. *****************************************************************************/
  1273. ObjectStruct *EditSrfControlPoint(ObjectStruct *PObjSrf, ObjectStruct *PObjPt,
  1274.                     RealType *UIndex, RealType *VIndex)
  1275. {
  1276.     ObjectStruct *SrfObj;
  1277.     CagdCtlPtStruct CagdCtlPt;
  1278.     CagdSrfStruct *Srf;
  1279.  
  1280.     ConvertCtlPt(PObjPt, &CagdCtlPt);
  1281.  
  1282.     Srf = CagdEditSingleSrfPt(PObjSrf -> U.Srf.Srf, &CagdCtlPt,
  1283.                   REAL_PTR_TO_INT(UIndex),
  1284.                   REAL_PTR_TO_INT(VIndex));
  1285.  
  1286.     SrfObj = GenSrfObject("", Srf, NULL);
  1287.  
  1288.     return SrfObj;
  1289. }
  1290.  
  1291. /*****************************************************************************
  1292. *  Editing of a single control point of a curve.                 *
  1293. *****************************************************************************/
  1294. ObjectStruct *RaiseCurveObject(ObjectStruct *PObjCrv, RealType *RNewOrder)
  1295. {
  1296.     ObjectStruct *CrvObj;
  1297.     CagdCrvStruct *TCrv,
  1298.     *Crv = PObjCrv -> U.Crv.Crv;
  1299.     int OldOrder = Crv -> Order,
  1300.     NewOrder = REAL_PTR_TO_INT(RNewOrder);
  1301.  
  1302.     if (NewOrder <= OldOrder) {
  1303.     WndwInputWindowPutStr("Order to raise less the current");
  1304.     return NULL;
  1305.     }
  1306.  
  1307.     while (OldOrder++ < NewOrder) {
  1308.     TCrv = CagdCrvDegreeRaise(Crv);
  1309.     if (Crv != PObjCrv -> U.Crv.Crv)
  1310.         CagdCrvFree(Crv);
  1311.     Crv = TCrv;
  1312.     }
  1313.  
  1314.     CrvObj = GenCrvObject("", Crv, NULL);
  1315.  
  1316.     return CrvObj;
  1317. }
  1318.  
  1319. /*****************************************************************************
  1320. *  Editing of a single control point of a curve.                 *
  1321. *****************************************************************************/
  1322. ObjectStruct *RaiseSurfaceObject(ObjectStruct *PObjSrf, RealType *RDir,
  1323.                              RealType *RNewOrder )
  1324. {
  1325.     ObjectStruct *SrfObj;
  1326.     CagdSrfStruct *TSrf,
  1327.     *Srf = PObjSrf -> U.Srf.Srf;
  1328.     int Dir = REAL_PTR_TO_INT(RDir),
  1329.     OldOrder = Dir == CAGD_CONST_U_DIR ? Srf -> VOrder : Srf -> UOrder,
  1330.     NewOrder = REAL_PTR_TO_INT(RNewOrder);
  1331.  
  1332.     if (NewOrder <= OldOrder) {
  1333.     WndwInputWindowPutStr("Order to raise less the current");
  1334.     return NULL;
  1335.     }
  1336.  
  1337.     while (OldOrder++ < NewOrder) {
  1338.     TSrf = CagdSrfDegreeRaise(Srf, Dir);
  1339.     if (Srf != PObjSrf -> U.Srf.Srf)
  1340.         CagdSrfFree(Srf);
  1341.     Srf = TSrf;
  1342.     }
  1343.  
  1344.     SrfObj = GenSrfObject("", Srf, NULL);
  1345.  
  1346.     return SrfObj;
  1347. }
  1348.  
  1349.